package  org.fantasy.common.eval;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.StringTokenizer;

public class BaseCalculator implements Calculator {
    /**
     * 运算过程中的符号数据堆栈类
     */
    private class Stacks {
	private LinkedList<Object> list = new LinkedList<Object>();

	int top = -1;

	public Object pop() {
	    Object temp = list.getFirst();
	    top--;
	    list.removeFirst();
	    return temp;
	}

	public void push(Object value) {
	    top++;
	    list.addFirst(value);
	}

	public Object top() {
	    return list.getFirst();
	}
    }

    private ArrayList<String> middleExp;// 存储中序表达式

    private String result;// 结果

    // 依据输入信息创建对象，将数值与操作符放入ArrayList中

    private ArrayList<String> rightExp;

    /**
     * 是否为操作符
     * 
     * @param operator
     * @return
     */
    private static boolean isOperator(String operator) {
	if ("+-*/()".contains(operator))
	    return true;
	else
	    return false;
    }

    public static void main(String avg[]) throws Exception {

	String input = new String();
	input = "-9"; // is.readLine().trim();
	// input = "(((-9)))";

	Calendar c = Calendar.getInstance();
	Calculator cal = null;
	for (int n = 0; n < 10000; n++) {
	    cal = new BaseCalculator(input);
	    cal.eval();
	    if (n == 0) {
		System.out.println(cal);
	    }
	}
	Calendar d = Calendar.getInstance();
	System.out.println("Spend time:"
		+ (d.getTimeInMillis() - c.getTimeInMillis()));

    }

    /**
     * 优先级比较
     * 
     * @param operator
     * @return
     */
    private static int priority(String operator) {
	if ("+-(".contains(operator))
	    return 1;
	else if ("*/".contains(operator))
	    return 2;
	else
	    return 0;
    }

    /**
     * 两数简单运算
     * 
     * @param operator
     * @param a
     * @param b
     * @return
     */
    private static String simpleCal(String op, String a, String b) {
	double x = Double.parseDouble(b);
	double y = Double.parseDouble(a);
	double z = 0;
	if (op.equals("+"))
	    z = x + y;
	else if (op.equals("-"))
	    z = x - y;
	else if (op.equals("*"))
	    z = x * y;
	else if (op.equals("/"))
	    z = x / y;
	else
	    z = 0;
	return String.valueOf(z);
    }

    public BaseCalculator() {

    }

    public BaseCalculator(String exp) throws Exception {
	input(exp);
    }

    /**
     * 进行值的计算，认为已经产生了右缀表达式
     * 
     * @return
     */
    private String calculate() {
	Stacks aStack = new Stacks();
	String op1, op2, is = null;
	Iterator<String> it = rightExp.iterator();
	while (it.hasNext()) {
	    is = it.next();
	    if (isOperator(is)) {
		op1 = (String) aStack.pop();
		op2 = (String) aStack.pop();
		aStack.push(simpleCal(is, op1, op2));
	    } else
		aStack.push(is);
	}
	result = (String) aStack.pop();

	return result;
    }

    /**
     * 仅在有正确input时运行此方法
     */
    private void genRightExp() {
	if (rightExp == null)
	    rightExp = new ArrayList<String>();
	else
	    rightExp.clear();
	Stacks aStack = new Stacks();
	String operator;
	int position = 0;
	while (true) {
	    if (isOperator(middleExp.get(position))) {
		if (aStack.top == -1 || (middleExp.get(position)).equals("(")) {
		    aStack.push(middleExp.get(position));
		} else {
		    if ((middleExp.get(position)).equals(")")) {
			while (!((String) aStack.top()).equals("(")) {
			    operator = (String) aStack.pop();
			    rightExp.add(operator);
			}
			aStack.pop();
		    } else {
			while (aStack.top != -1
				&& priority((String) middleExp.get(position)) <= priority((String) aStack
					.top()) && !aStack.top().equals("(")) {
			    operator = (String) aStack.pop();
			    rightExp.add(operator);
			}
			aStack.push(middleExp.get(position));
		    }
		}
	    } else
		rightExp.add(middleExp.get(position));
	    position++;
	    if (position >= middleExp.size())
		break;
	}
	while (aStack.top != -1) {
	    operator = (String) aStack.pop();
	    rightExp.add(operator);
	}
    }

    /**
     * 输入同时，会产生其右缀表达式并计算
     */
    public void input(String exp) throws Exception {
	if (middleExp == null)
	    middleExp = new ArrayList<String>();
	else
	    middleExp.clear();
	exp = "(" + exp + ")";
	exp = exp.replace(" ", "").replace("(+", "(0+").replace("(-", "(0-");
	StringTokenizer st = new StringTokenizer(exp, "+-*/()", true);
	while (st.hasMoreElements()) {
	    middleExp.add(st.nextToken());
	}
	genRightExp();
	calculate();
    }

    @Override
    public String toString() {
	if (middleExp == null)
	    return "";
	String sr = "";
	for (String s : middleExp) {
	    sr += s + " ";
	}
	sr += "\n";
	for (String s : rightExp) {
	    sr += s + " ";
	}
	sr += "\n";
	sr += result;
	return sr;
    }

    /**
     * 取得表达式的值
     */
    public BigDecimal eval() throws Exception {
	if (middleExp == null)
	    return new BigDecimal(0);
	return new BigDecimal(result);
    }
}
